package com.github.baichuan.application.scaffold.jdbc;

import com.github.baichuan.immutable.Tuple2;
import com.github.baichuan.web.audit.AuditLog;
import com.github.baichuan.application.scaffold.dto.audit.AuditLogQueryCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Component
@ConditionalOnBean(name = "audit-jdbc-template")
public class AuditLogRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Page<AuditLog> query(AuditLogQueryCriteria queryCriteria, Pageable pageable){
        Tuple2<String, Object[]> tuple2 = queryCriteria.where();
        String where = tuple2.get_1();
        Object[] params = tuple2.get_2();

        String countSql = "select count(*) from operation where " + where;
        Integer total = jdbcTemplate.queryForObject(countSql, params, Integer.class);

        String querySql = "select operator, date_format(operation_time, '%Y-%m-%d %H:%i:%s.%S') as operation_time, application, `name`, `code`, ip, `path`, request, response, response_status  from operation where "
                + where + " order by operation_time desc limit " + pageable.getOffset() + ", " + pageable.getPageSize();
        List<AuditLog> list = jdbcTemplate.query(querySql, params, new Mapper());
        PageImpl<AuditLog> page = new PageImpl<>(list, pageable, total);
        return page;
    }

    private static class Mapper implements RowMapper<AuditLog> {

        @Override
        public AuditLog mapRow(ResultSet rs, int rowNum) throws SQLException {
            AuditLog log = new AuditLog();
            log.setOperator(rs.getString("operator"));
            log.setOperationTime(rs.getString("operation_time"));
            log.setApplication(rs.getString("application"));
            log.setName(rs.getString("name"));
            log.setCode(rs.getString("code"));
            log.setIp(rs.getString("ip"));
            log.setPath(rs.getString("path"));
            log.setRequest(rs.getString("request"));
            log.setResponse(rs.getString("response"));
            log.setResponseStatus(rs.getShort("response_status"));
            return log;
        }
    }
}
